#pragma once

#include <iostream>
#include <map>
#include <string>
#include <vector>

namespace lib
{

// idea from boost any but make it more simple and don't use type_info.
class Any
{
   public:
    Any() : content_(NULL) {}

    template <typename ValueType> explicit Any(const ValueType &value) : content_(new Holder<ValueType>(value)) {}

    Any(const Any &other) : content_(other.content_ ? other.content_->Clone() : nullptr) {}

    ~Any()
    {
        delete content_;
    }

    template <typename ValueType> ValueType *AnyCast()
    {
        return content_ ? &(static_cast<Holder<ValueType> *>(content_)->held_) : nullptr;
    }

   private:
    class PlaceHolder
    {
       public:
        virtual ~PlaceHolder() {}
        virtual PlaceHolder *Clone() const = 0;
    };

    template <typename ValueType> class Holder : public PlaceHolder
    {
       public:
        explicit Holder(const ValueType &value) : held_(value) {}
        virtual ~Holder() {}
        virtual PlaceHolder *Clone() const
        {
            return new Holder(held_);
        }

        ValueType held_;
    };

    PlaceHolder *content_;
};

class ObjectFactory
{
   public:
    ObjectFactory() {}
    virtual ~ObjectFactory() {}
    virtual Any NewInstance()
    {
        return Any();
    }
    ObjectFactory(const ObjectFactory &) = delete;
    ObjectFactory &operator=(const ObjectFactory &) = delete;

   private:
};

typedef std::map<std::string, ObjectFactory *> FactoryMap;
typedef std::map<std::string, FactoryMap> BaseClassMap;
BaseClassMap &GlobalFactoryMap();

bool GetRegisteredClasses(const std::string &base_class_name, std::vector<std::string> *registered_derived_classes_names);

}  // namespace lib

#define MODULE_REGISTERER(base_class)                                                                                              \
    class base_class##Registerer                                                                                                   \
    {                                                                                                                              \
        typedef ::lib::Any Any;               /* 引用 Any 类型，代表一个泛型容器，可以存储任意类型 */        \
        typedef ::lib::FactoryMap FactoryMap; /* 引用 FactoryMap 类型，表示工厂映射，用于存储类实例化信息 */ \
                                                                                                                                   \
       public:                                                                                                                     \
        /* 通过名字获取对应类的实例 */                                                                                 \
        static base_class *GetInstanceByName(const std::string &name)                                                              \
        {                                                                                                                          \
            /* 获取全局工厂映射中当前基类的实例映射表 */                                                        \
            FactoryMap &map = ::lib::GlobalFactoryMap()[#base_class];                                                              \
                                                                                                                                   \
            /* 查找映射表中是否存在该名称的类实例 */                                                              \
            FactoryMap::iterator iter = map.find(name);                                                                            \
            if (iter == map.end())                                                                                                 \
            {                                                                                                                      \
                /* 如果没找到，遍历并打印已有的类实例名称 */                                                    \
                for (auto c : map)                                                                                                 \
                {                                                                                                                  \
                    std::cout << "Instance:" << c.first << std::endl;                                                              \
                }                                                                                                                  \
                std::cout << "Get instance " << name << " failed." << std::endl;                                                   \
                return nullptr; /* 返回空指针，表示获取失败 */                                                         \
            }                                                                                                                      \
            /* 通过工厂函数实例化对象 */                                                                                \
            Any object = iter->second->NewInstance();                                                                              \
            /* 将实例转换为 base_class 指针类型并返回 */                                                              \
            return *(object.AnyCast<base_class *>());                                                                              \
        }                                                                                                                          \
                                                                                                                                   \
        /* 获取所有已注册类的实例列表 */                                                                              \
        static std::vector<base_class *> GetAllInstances()                                                                         \
        {                                                                                                                          \
            std::vector<base_class *> instances; /* 用于存储所有类实例的向量 */                                        \
            /* 获取全局工厂映射中当前基类的实例映射表 */                                                        \
            FactoryMap &map = ::lib::GlobalFactoryMap()[#base_class];                                                              \
            instances.reserve(int(map.size())); /* 为向量预留空间，大小等于映射表的大小 */                       \
            for (auto item : map)                                                                                                  \
            {                                                                                                                      \
                /* 实例化每个类并添加到实例向量中 */                                                                \
                Any object = item.second->NewInstance();                                                                           \
                instances.push_back(*(object.AnyCast<base_class *>()));                                                            \
            }                                                                                                                      \
            return instances; /* 返回包含所有类实例的向量 */                                                           \
        }                                                                                                                          \
                                                                                                                                   \
        /* 获取唯一类实例的名称，假设只有一个类注册在映射表中 */                                          \
        static const std::string GetUniqInstanceName()                                                                             \
        {                                                                                                                          \
            /* 获取全局工厂映射中当前基类的实例映射表 */                                                        \
            FactoryMap &map = ::lib::GlobalFactoryMap()[#base_class];                                                              \
            /* 返回映射表第一个类的名称（假设只有一个类） */                                                  \
            return map.begin()->first;                                                                                             \
        }                                                                                                                          \
                                                                                                                                   \
        /* 获取唯一类的实例，假设映射表中只注册了一个类 */                                                   \
        static base_class *GetUniqInstance()                                                                                       \
        {                                                                                                                          \
            /* 获取全局工厂映射中当前基类的实例映射表 */                                                        \
            FactoryMap &map = ::lib::GlobalFactoryMap()[#base_class];                                                              \
            /* 实例化映射表中第一个类并返回该实例 */                                                              \
            Any object = map.begin()->second->NewInstance();                                                                       \
            return *(object.AnyCast<base_class *>());                                                                              \
        }                                                                                                                          \
                                                                                                                                   \
        /* 判断是否存在名称为 name 的类实例 */                                                                        \
        static bool IsValid(const std::string &name)                                                                               \
        {                                                                                                                          \
            /* 获取全局工厂映射中当前基类的实例映射表 */                                                        \
            FactoryMap &map = ::lib::GlobalFactoryMap()[#base_class];                                                              \
            /* 如果未找到该名称的类，输出 0 和映射表大小 */                                                     \
            if (map.find(name) == map.end())                                                                                       \
                printf("GlobalFactoryMap %s 0 %d ------\n", name.c_str(), int(map.size()));                                        \
            else                                                                                                                   \
                /* 如果找到了，输出 1 和映射表大小 */                                                                \
                printf("GlobalFactoryMap %s 1 %d ------\n", name.c_str(), int(map.size()));                                        \
            /* 返回该类是否存在的布尔值 */                                                                             \
            return map.find(name) != map.end();                                                                                    \
        }                                                                                                                          \
    };

// 宏定义，用于注册类到工厂映射中
#define MODULE_CLASS(clazz, name)                                                                                   \
    namespace                                                                                                       \
    {                                                                                                               \
        /* 定义一个工厂类 ObjectFactory##name，继承自 lib::ObjectFactory*/                               \
        class ObjectFactory##name : public ::lib::ObjectFactory                                                     \
        {                                                                                                           \
           public:                                                                                                  \
            /* 析构函数*/                                                                                       \
            virtual ~ObjectFactory##name() {}                                                                       \
            /* 创建新实例的函数，返回一个 lib::Any 类型对象*/                                      \
            virtual ::lib::Any NewInstance()                                                                        \
            {                                                                                                       \
                return ::lib::Any(new name()); /* 创建 name 类的实例并包装到 lib::Any 中返回 */        \
            }                                                                                                       \
        };                                                                                                          \
        /* 使用 __attribute__((constructor)) 标记，在程序加载时执行函数 */                           \
        static __attribute__((constructor)) void RegisterFactory##name()                                            \
        {                                                                                                           \
            /*  获取全局工厂映射表，并找到与 clazz 对应的工厂映射                           */ \
            ::lib::FactoryMap &map = ::lib::GlobalFactoryMap()[#clazz];                                             \
            /*  如果当前 name 对应的类尚未注册到 map 中，则注册  */                               \
            if (map.find(#name) == map.end())                                                                       \
                map[#name] = new ObjectFactory##name();                                                             \
            /*  打印调试信息，判断 name 是否成功注册到 map 中*/                                    \
            if (map.find(#name) == map.end())                                                                       \
                printf("RegisterFactory %s 0 %d ------\n", #name, int(map.size()));                                 \
            else                                                                                                    \
                printf("RegisterFactory %s 1 %d ------\n", #name, int(map.size()));                                 \
        }                                                                                                           \
    }
